﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using SharedGenomics.Domain;
using SharedGenomics.Workbench.Models;

namespace SharedGenomics.Workbench.Tests.Models
{
    [TestClass]
    public class DataFilterResultsModelTests
    {
        private DataFilterResultsModel model;

        [TestInitialize]
        public void Setup()
        {
            this.model = new DataFilterResultsModel();
        }

        [TestMethod]
        public void ConstructorTest_InitiallyEmpty()
        {
            Assert.AreEqual(0, (new DataFilterResultsModel()).Count);
        }

        [TestMethod]
        public void ConstructorTest_NoInitialFilter()
        {
            var model = new DataFilterResultsModel();
            Assert.IsTrue(model.ShowIndividuals);
            Assert.IsTrue(model.ShowSnps);
        }

        [TestMethod]
        public void AddResultsTest()
        {
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "RS001", Reason = FilterReason.MAF, Value = "0.01" }, new EntityFilterSummary() { Id = "I001", Reason = FilterReason.CategoricalFilter, Value = "Asian" } });
            Assert.AreEqual(2, this.model.ResultCount);
        }

        [TestMethod]
        public void AddResultsTest_Null()
        {
            this.model.LoadItems(null);
            Assert.AreEqual(0, this.model.ResultCount);
        }

        [TestMethod]
        public void AddResultsTest_RaisesChangedEvent()
        {
            bool eventRaised = false;
            this.model.ListChanged += (o, e) => { eventRaised = true; };
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "RS001", Reason = FilterReason.MAF, Value = "0.0043563" } });
            Assert.IsTrue(eventRaised);
        }

        [TestMethod]
        public void ClearResultsTest()
        {
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "RS001", Reason = FilterReason.HardyWeinberg, Value = "0.0043" } });
            this.model.Clear();
            Assert.AreEqual(0, this.model.ResultCount);
        }

        [TestMethod]
        public void ClearResultsTest_RaisesChangedEvent()
        {
            bool eventRaised = false;
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "RS001", Reason = FilterReason.HardyWeinberg, Value = "0.0043" } });
            this.model.ListChanged += (o, e) => { eventRaised = true; };
            this.model.Clear();

            Assert.IsTrue(eventRaised);
        }

        [TestMethod]
        public void ShowSnpsTest_True()
        {
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "RS001", Reason = FilterReason.MAF, Value = "0.2334" } });
            this.model.ShowSnps = true;
            Assert.AreEqual(1, this.model.Count);
        }

        [TestMethod]
        public void ShowSnpsTest_False()
        {
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "RS001", Reason = FilterReason.MAF, Value = "0.2334" } });
            this.model.ShowSnps = false;
            Assert.AreEqual(0, this.model.Count());
        }

        [TestMethod]
        public void ShowSnpsTest_RaisesChangedEventOnChange()
        {
            bool eventRaised = false;
            this.model.ShowSnps = true;
            this.model.ListChanged += (o, e) => { eventRaised = true; };
            this.model.ShowSnps = false;

            Assert.IsTrue(eventRaised);
        }

        [TestMethod]
        public void ShowSnpsTest_DoesNotRaiseChangedEventOnSame()
        {
            bool eventRaised = false;
            this.model.ShowSnps = true;
            this.model.ListChanged += (o, e) => { eventRaised = true; };
            this.model.ShowSnps = true;

            Assert.IsFalse(eventRaised);
        }

        [TestMethod]
        public void ShowIndividualsTest_RaisesChangedEventOnChange()
        {
            bool eventRaised = false;
            this.model.ShowIndividuals = true;
            this.model.ListChanged += (o, e) => { eventRaised = true; };
            this.model.ShowIndividuals = false;

            Assert.IsTrue(eventRaised);
        }

        [TestMethod]
        public void ShowIndividualsTest_DoesNotRaiseChangedEventOnSame()
        {
            bool eventRaised = false;
            this.model.ShowIndividuals = true;
            this.model.ListChanged += (o, e) => { eventRaised = true; };
            this.model.ShowIndividuals = true;

            Assert.IsFalse(eventRaised);
        }

        [TestMethod]
        public void ShowIndividualsTest_True()
        {
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "I1", Reason = FilterReason.CategoricalFilter, Value = "Asian" } });
            this.model.ShowIndividuals = true;
            Assert.AreEqual(1, this.model.Count);
        }

        [TestMethod]
        public void ShowIndividualsTest_False()
        {
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "I1", Reason = FilterReason.CategoricalFilter, Value = "Asian" } });
            this.model.ShowIndividuals = false;
            Assert.AreEqual(0, this.model.Count);
        }

        [TestMethod]
        public void GetFilterSummaryByIdTest_Present()
        {
            EntityFilterSummary summary = new EntityFilterSummary() { Id = "ABC", Reason = FilterReason.HardyWeinberg, Value = "0.11" };
            this.model.LoadItems(new[] { summary });
            Assert.AreEqual(summary, this.model.GetFilterSummaryById("ABC"));
        }

        [TestMethod]
        public void GetFilterSummaryByIdTest_Present_DifferentCase()
        {
            EntityFilterSummary summary = new EntityFilterSummary() { Id = "ABC", Reason = FilterReason.HardyWeinberg, Value = "0.11" };
            this.model.LoadItems(new[] { summary });
            Assert.AreEqual(summary, this.model.GetFilterSummaryById("abc"));
        }

        [TestMethod]
        public void GetFilterSummaryByIdTest_NotPresent()
        {
            Assert.IsNull(this.model.GetFilterSummaryById("id"));
        }

        [TestMethod]
        public void GetFilterSummaryByIdTest_Null()
        {
            this.model.LoadItems(new[] { new EntityFilterSummary() { Id = "1", Reason = FilterReason.CategoricalFilter, Value = "ethnic" } });
            Assert.IsNull(this.model.GetFilterSummaryById(null));
        }
    }
}
